package com.rede.didiok.admin.service.impl;

import java.util.*;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rede.didiok.admin.dao.CategoryMenuDao;
import com.rede.didiok.admin.entity.AdminEntity;
import com.rede.didiok.admin.entity.CategoryMenuEntity;
import com.rede.didiok.admin.entity.RoleEntity;
import com.rede.didiok.admin.service.AdminService;
import com.rede.didiok.admin.service.CategoryMenuService;
import com.rede.didiok.admin.service.RoleService;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.RedisConf;
import com.rede.didiok.common.constant.conf.SQLConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.dto.admin.CategoryMenuDto;
import com.rede.didiok.common.enums.MenuTypeEnum;
import com.rede.didiok.common.enums.StatusEnum;
import com.rede.didiok.common.exception.exceptionType.QueryException;
import com.rede.didiok.common.utils.*;


@Service("categoryMenuService")
public class CategoryMenuServiceImpl extends ServiceImpl<CategoryMenuDao, CategoryMenuEntity> implements CategoryMenuService {

    @Autowired
    RedisUtil redisUtil;
    @Resource
    AdminService adminService;
    @Resource
    RoleService roleService;


    /***************************** didiok-admin:start **************************/
    // region  didiok-admin

    /**
     * 获取菜单列表
     *
     * @param categoryMenuDto
     * @return
     */
    @Override
    public Map<String, Object> getPageList(CategoryMenuDto categoryMenuDto) {
        Map<String, Object> resultMap = new HashMap<>();
        QueryWrapper<CategoryMenuEntity> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(categoryMenuDto.getKeyword()) && !StringUtils.isEmpty(categoryMenuDto.getKeyword().trim())) {
            queryWrapper.like(SQLConf.NAME, categoryMenuDto.getKeyword().trim());
        }

        if (categoryMenuDto.getMenuLevel() != 0) {
            queryWrapper.eq(SQLConf.MENU_LEVEL, categoryMenuDto.getMenuLevel());
        }

        Page<CategoryMenuEntity> page = new Page<>();
        page.setCurrent(categoryMenuDto.getCurrentPage());
        page.setSize(categoryMenuDto.getPageSize());
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.orderByDesc(SQLConf.SORT);
        IPage<CategoryMenuEntity> pageList = this.page(page, queryWrapper);
        List<CategoryMenuEntity> list = pageList.getRecords();

        List<String> ids = new ArrayList<>();
        list.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getParentUid())) {
                ids.add(item.getParentUid());
            }
        });

        if (ids.size() > 0) {
            Collection<CategoryMenuEntity> parentList = this.listByIds(ids);
            Map<String, CategoryMenuEntity> map = new HashMap<>();
            parentList.forEach(item -> {
                map.put(item.getUid(), item);
            });

            list.forEach(item -> {
                if (StringUtils.isNotEmpty(item.getParentUid())) {
                    item.setParentCategoryMenu(map.get(item.getParentUid()));
                }
            });

            resultMap.put(SysConf.OTHER_DATA, parentList);
        }
        pageList.setRecords(list);
        resultMap.put(SysConf.DATA, pageList);
        return resultMap;
    }

    /**
     * 获取全部菜单列表
     *
     * @param keyword
     * @return
     */
    @Override
    public List<CategoryMenuEntity> getAllList(String keyword) {
        QueryWrapper<CategoryMenuEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.MENU_LEVEL, Constants.STR_ONE);
        if (StringUtils.isNotEmpty(keyword)) {
            queryWrapper.eq(SQLConf.UID, keyword);
        }
        queryWrapper.orderByDesc(SQLConf.SORT);
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.eq(SQLConf.MENU_TYPE, MenuTypeEnum.MENU);
        List<CategoryMenuEntity> list = this.list(queryWrapper);

        //获取所有的ID，去寻找他的子目录
        List<String> ids = new ArrayList<>();
        list.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getUid())) {
                ids.add(item.getUid());
            }
        });

        QueryWrapper<CategoryMenuEntity> childWrapper = new QueryWrapper<>();
        childWrapper.in(SQLConf.PARENT_UID, ids);
        childWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        Collection<CategoryMenuEntity> childList = this.list(childWrapper);

        //获取所有的二级菜单，去寻找他的子按钮
        List<String> secondMenuUids = new ArrayList<>();
        childList.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getUid())) {
                secondMenuUids.add(item.getUid());
            }
        });

        QueryWrapper<CategoryMenuEntity> buttonWrapper = new QueryWrapper<>();
        buttonWrapper.in(SQLConf.PARENT_UID, secondMenuUids);
        buttonWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        Collection<CategoryMenuEntity> buttonList = this.list(buttonWrapper);

        Map<String, List<CategoryMenuEntity>> map = new HashMap<>();
        buttonList.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getParentUid())) {
                if (map.get(item.getParentUid()) == null) {
                    List<CategoryMenuEntity> tempList = new ArrayList<>();
                    tempList.add(item);
                    map.put(item.getParentUid(), tempList);
                } else {
                    List<CategoryMenuEntity> tempList = map.get(item.getParentUid());
                    tempList.add(item);
                    map.put(item.getParentUid(), tempList);
                }
            }
        });

        // 给二级菜单设置三级按钮
        childList.forEach(item -> {
            if (map.get(item.getUid()) != null) {
                List<CategoryMenuEntity> tempList = map.get(item.getUid());
                Collections.sort(tempList, new Comparator<CategoryMenuEntity>() {

                    /*
                     * int compare(CategoryMenuEntity p1, CategoryMenuEntity p2) 返回一个基本类型的整型，
                     * 返回负数表示：p1 小于p2，
                     * 返回0 表示：p1和p2相等，
                     * 返回正数表示：p1大于p2
                     */
                    @Override
                    public int compare(CategoryMenuEntity o1, CategoryMenuEntity o2) {

                        //按照CategoryMenu的Sort进行降序排列
                        if (o1.getSort() > o2.getSort()) {
                            return -1;
                        }
                        if (o1.getSort().equals(o2.getSort())) {
                            return 0;
                        }
                        return 1;
                    }

                });
                item.setChildCategoryMenu(tempList);
            }
        });


        // 给一级菜单设置二级菜单
        for (CategoryMenuEntity parentItem : list) {
            List<CategoryMenuEntity> tempList = new ArrayList<>();
            for (CategoryMenuEntity item : childList) {

                if (item.getParentUid().equals(parentItem.getUid())) {
                    tempList.add(item);
                }
            }
            Collections.sort(tempList);
            parentItem.setChildCategoryMenu(tempList);
        }
        return list;
    }

    /**
     * 获取某个用户允许访问的菜单列表
     *
     * @param userName
     * @return
     */
    @Override
    public List<CategoryMenuEntity> getCategoryMenuByUserName(String userName) {
        Boolean isEmail = CheckUtils.checkEmail(userName);
        Boolean isMobile = CheckUtils.checkMobileNumber(userName);
        QueryWrapper<AdminEntity> queryWrapper = new QueryWrapper<>();
        if (isEmail) {
            queryWrapper.eq(SQLConf.EMAIL, userName);
        } else if (isMobile) {
            queryWrapper.eq(SQLConf.MOBILE, userName);
        } else {
            queryWrapper.eq(SQLConf.USER_NAME, userName);
        }
        queryWrapper.last(SysConf.LIMIT_ONE);
        queryWrapper.eq(SysConf.STATUS, StatusEnum.ENABLE);
        AdminEntity admin = adminService.getOne(queryWrapper);
        List<CategoryMenuEntity> hasPermission;
        if (admin == null) {
            throw new QueryException(String.format("[%s]该账号未注册,无法登录", userName));
        } else {
            //查询出角色信息封装到admin中
            RoleEntity role = roleService.getById(admin.getRoleUid());
            if (role == null) {
                throw new QueryException(String.format("[%s]该账号未配置角色,无法登录", userName));
            }
            List<String> roleNames = new ArrayList<>();
            roleNames.add(role.getRoleName());
            admin.setRoleNames(roleNames);
            List<String> categoryMenuUids = new ArrayList<>();
            String[] uids = role.getCategoryMenuUids().replace("[", "").replace("]", "").replace("\"", "").split(",");
            categoryMenuUids.addAll(Arrays.asList(uids));
            hasPermission =
                    this.list(
                            new LambdaQueryWrapper<CategoryMenuEntity>()
                                    .in(CategoryMenuEntity::getUid, categoryMenuUids)
                                    .eq(CategoryMenuEntity::getStatus, StatusEnum.ENABLE)
                    );
        }
        return hasPermission;
    }

    /**
     * 获取所有二级菜单-按钮列表
     *
     * @param keyword
     * @return
     */
    @Override
    public List<CategoryMenuEntity> getButtonAllList(String keyword) {
        QueryWrapper<CategoryMenuEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.MENU_LEVEL, Constants.STR_TWO);
        queryWrapper.orderByDesc(SQLConf.SORT);
        if (StringUtils.isNotEmpty(keyword)) {
            queryWrapper.eq(SQLConf.UID, keyword);
        }
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.eq(SQLConf.MENU_TYPE, MenuTypeEnum.MENU);
        List<CategoryMenuEntity> list = this.list(queryWrapper);

        //获取所有的ID，去寻找他的子目录
        List<String> ids = new ArrayList<>();
        list.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getUid())) {
                ids.add(item.getUid());
            }
        });

        QueryWrapper<CategoryMenuEntity> childWrapper = new QueryWrapper<>();
        childWrapper.in(SQLConf.PARENT_UID, ids);
        childWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        Collection<CategoryMenuEntity> childList = this.list(childWrapper);
        Set<String> secondUidSet = new HashSet<>();
        Map<String, List<CategoryMenuEntity>> map = new HashMap<>();
        childList.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getParentUid())) {

                secondUidSet.add(item.getParentUid());

                if (map.get(item.getParentUid()) == null) {
                    List<CategoryMenuEntity> tempList = new ArrayList<>();
                    tempList.add(item);
                    map.put(item.getParentUid(), tempList);
                } else {
                    List<CategoryMenuEntity> tempList = map.get(item.getParentUid());
                    tempList.add(item);
                    map.put(item.getParentUid(), tempList);
                }
            }
        });

        // 过滤不在Button列表中的二级菜单
        List<CategoryMenuEntity> secondCategoryMenuList = new ArrayList<>();
        for (CategoryMenuEntity secondCategoryMenu : list) {
            for (String uid : secondUidSet) {
                if (secondCategoryMenu.getUid().equals(uid)) {
                    secondCategoryMenuList.add(secondCategoryMenu);
                    break;
                }
            }
        }

        // 给二级菜单设置三级按钮
        secondCategoryMenuList.forEach(item -> {
            if (map.get(item.getUid()) != null) {
                List<CategoryMenuEntity> tempList = map.get(item.getUid());
                Collections.sort(tempList);
                item.setChildCategoryMenu(tempList);
            }
        });
        return list;
    }

    /**
     * 新增菜单
     *
     * @param categoryMenuDto
     */
    @Override
    public String addCategoryMenu(CategoryMenuDto categoryMenuDto) {
        //如果是一级菜单，将父ID清空
        if (categoryMenuDto.getMenuLevel() == 1) {
            categoryMenuDto.setParentUid("");
        }
        CategoryMenuEntity categoryMenu = new CategoryMenuEntity();
        categoryMenu.setParentUid(categoryMenuDto.getParentUid());
        categoryMenu.setSort(categoryMenuDto.getSort());
        categoryMenu.setIcon(categoryMenuDto.getIcon());
        categoryMenu.setSummary(categoryMenuDto.getSummary());
        categoryMenu.setMenuLevel(categoryMenuDto.getMenuLevel());
        categoryMenu.setMenuType(categoryMenuDto.getMenuType());
        categoryMenu.setName(categoryMenuDto.getName());
        categoryMenu.setUrl(categoryMenuDto.getUrl());
        categoryMenu.setIsShow(categoryMenuDto.getIsShow());
        categoryMenu.setIsJumpExternalUrl(categoryMenuDto.getIsJumpExternalUrl());
        categoryMenu.insert();
        return MessageConf.INSERT_SUCCESS;
    }

    /**
     * 编辑菜单
     *
     * @param categoryMenuDto
     */
    @Override
    public String editCategoryMenu(CategoryMenuDto categoryMenuDto) {
        CategoryMenuEntity categoryMenu = this.getById(categoryMenuDto.getUid());
        categoryMenu.setParentUid(categoryMenuDto.getParentUid());
        categoryMenu.setSort(categoryMenuDto.getSort());
        categoryMenu.setIcon(categoryMenuDto.getIcon());
        categoryMenu.setSummary(categoryMenuDto.getSummary());
        categoryMenu.setMenuLevel(categoryMenuDto.getMenuLevel());
        categoryMenu.setMenuType(categoryMenuDto.getMenuType());
        categoryMenu.setName(categoryMenuDto.getName());
        categoryMenu.setUrl(categoryMenuDto.getUrl());
        categoryMenu.setIsShow(categoryMenuDto.getIsShow());
        categoryMenu.setIsJumpExternalUrl(categoryMenuDto.getIsJumpExternalUrl());
        categoryMenu.updateById();
        // 修改成功后，需要删除redis中所有的admin访问路径
        deleteAdminVisitUrl();
        return MessageConf.UPDATE_SUCCESS;
    }

    /**
     * 批量删除菜单
     *
     * @param categoryMenuDto
     */
    @Override
    public String deleteCategoryMenu(CategoryMenuDto categoryMenuDto) {
        QueryWrapper<CategoryMenuEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.in(SQLConf.PARENT_UID, categoryMenuDto.getUid());
        Integer menuCount = this.count(queryWrapper);
        if (menuCount > 0) {
            return ResultUtil.errorWithMessage(MessageConf.CHILDREN_MENU_UNDER_THIS_MENU);
        }
        CategoryMenuEntity categoryMenu = this.getById(categoryMenuDto.getUid());
        categoryMenu.setStatus(StatusEnum.DISABLED);
        categoryMenu.updateById();
        // 修改成功后，需要删除redis中所有的admin访问路径
        deleteAdminVisitUrl();
        return ResultUtil.successWithMessage(MessageConf.DELETE_SUCCESS);
    }

    /**
     * 置顶菜单
     *
     * @param categoryMenuDto
     */
    @Override
    public String stickCategoryMenu(CategoryMenuDto categoryMenuDto) {
        CategoryMenuEntity categoryMenu = this.getById(categoryMenuDto.getUid());
        //查找出最大的那一个
        QueryWrapper<CategoryMenuEntity> queryWrapper = new QueryWrapper<>();
        //如果是二级菜单 或者 按钮，就在当前的兄弟中，找出最大的一个
        if (categoryMenu.getMenuLevel() == Constants.NUM_TWO || categoryMenu.getMenuType() == MenuTypeEnum.BUTTON) {
            queryWrapper.eq(SQLConf.PARENT_UID, categoryMenu.getParentUid());
        }
        queryWrapper.eq(SQLConf.MENU_LEVEL, categoryMenu.getMenuLevel());
        queryWrapper.orderByDesc(SQLConf.SORT);
        queryWrapper.last(SysConf.LIMIT_ONE);
        CategoryMenuEntity maxSort = this.getOne(queryWrapper);
        if (StringUtils.isEmpty(maxSort.getUid())) {
            return ResultUtil.errorWithMessage(MessageConf.OPERATION_FAIL);
        }
        Integer sortCount = maxSort.getSort() + 1;
        categoryMenu.setSort(sortCount);
        categoryMenu.setUpdateTime(new Date());
        categoryMenu.updateById();
        return ResultUtil.successWithMessage(MessageConf.OPERATION_SUCCESS);
    }


    // endregion
    /***************************** didiok-admin:end **************************/



    /***************************** didiok-web:start **************************/
    // region didiok-web

    // endregion
    /***************************** didiok-web:end **************************/

    /**
     * 删除Redis中管理员的访问路径
     */
    private void deleteAdminVisitUrl() {
        Set<String> keys = redisUtil.keys(RedisConf.ADMIN_VISIT_MENU + "*");
        redisUtil.delete(keys);
    }

}